﻿using System.Linq;
using Daemon.Common;
using Daemon.Common.Helpers;
using Daemon.Infrustructure.EF;
using Daemon.Repository.EF.Enums;
using Daemon.Repository.Contract;
using Daemon.Model;
using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using Daemon.Data.Infrastructure.FrameWork;

namespace Daemon.Repository.EF
{
    public class SystemMenuRepository : Repository<SystemMenu>, ISystemMenuRepository
    {
        protected override Expression<Func<SystemMenu, int>> PrimaryKeyExpression => r => r.Id;

        public SystemMenuRepository(ApiDBContent context) : base(context)
        {
        }

        protected override void UpdateEntitiesAfterDelete(IEnumerable<SystemMenu> entities, ApiDBContent context)
        {
            var ids = entities.Select(r => r.Id).ToList();
            var systemMenus = context.SystemMenus.ToList();
            var children = new List<SystemMenu>();
            ids.ForEach(id =>
            {
                children.AddRange(GetChildren(systemMenus, id));
            });

            context.SystemMenus.RemoveRange(children);
        }

        protected override IEnumerable<SystemMenu> IncludeRelationships(IEnumerable<SystemMenu> entities, ApiDBContent db)
        {
            SetChildren(entities);
            return entities;
        }

        protected override void UpdateEntitiesBeforeCreate(IEnumerable<SystemMenu> entities, ApiDBContent context)
        {
            entities.ForEach(entity =>
            {
                entity.AddTime = DateTime.Now;
            });

            base.UpdateEntitiesBeforeCreate(entities, context);
        }

        private void SetChildren(IEnumerable<SystemMenu> entities)
        {
            BuildTree(entities);
        }

        private void BuildTree(IEnumerable<SystemMenu> nodes, int? parentId = null)
        {
            var children = nodes.Where(n => n.FatherId == parentId).ToList();
            foreach (var child in children)
            {
                BuildTree(nodes, child.Id);
            }

            foreach (var node in children)
            {
                node.Children = children;
            }
        }

        private List<SystemMenu> GetChildren(IEnumerable<SystemMenu> nodes, int parentId, List<SystemMenu> result = null)
        {
            if (result == null)
            {
                result = new List<SystemMenu>();
            }

            var children = nodes.Where(r => r.FatherId == parentId);
            if (children.Any())
            {
                result.AddRange(children);
                foreach (var child in children)
                {
                    GetChildren(nodes, child.Id, result);
                }
            }

            return result;
        }
    }
}
